package uav.util.deepsort;


import org.opencv.core.Mat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

public class DeepSort {
    private ObjectTracker tracker = new ObjectTracker();
    private HashMap<Integer, ArrayList> clsBoxHashMap=new HashMap();
    private HashMap<Integer, ObjectTracker> clsTrackerHashMap=new HashMap();
    private List<float[]> detList=new ArrayList<>();
    private static final Logger logger = LoggerFactory.getLogger(DeepSort.class);
    public DeepSort(){

    }
    public static void main(String[] args) {
        ObjectTracker tracker = new ObjectTracker();

        // 模拟输入数据（检测框中心坐标）
        List<double[]> frame1Detections = Arrays.asList(
                new double[]{100, 200},
                new double[]{600, 200},
                new double[]{300, 150}
        );

        List<double[]> frame2Detections = Arrays.asList(
                new double[]{100, 200},
                new double[]{500, 500},
                new double[]{300, 150},
                new double[]{400, 150}
        );

        List<double[]> frame3Detections = Arrays.asList(
                new double[]{100, 200},
                new double[]{500, 500},
                new double[]{300, 150},
                new double[]{400, 150}
        );

        // 处理第一帧
        tracker.processDetections(frame1Detections,null ,-1,"N",null);
        printTracks(tracker.getActiveTracks());

        // 处理第二帧
        tracker.processDetections(frame2Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());

        // 处理第三帧
        tracker.processDetections(frame3Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());

        // 处理第4帧
        tracker.processDetections(frame3Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());
// 处理第8帧
        tracker.processDetections(frame1Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());
        // 处理第5帧
        tracker.processDetections(frame3Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());

        // 处理第6帧
        tracker.processDetections(frame3Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());

        // 处理第7帧
        tracker.processDetections(frame3Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());
        // 处理第8帧
        tracker.processDetections(frame1Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());
        // 处理第8帧
        tracker.processDetections(frame1Detections,null,-1,"N",null);
        printTracks(tracker.getActiveTracks());
    }
    /**
     * 目标跟踪更新
     *
     * @param detectorData 此处是根据YOLO10的OrtSession.Result output 返回值定的，不同的版本，不一样，自己改
     *          * 原有的识别物的BOX 向量是6个，
     *          * 第一个BOX[0] :目标物左上角顶点的X坐标
     *          * 第二个BOX[1] :目标物左上角顶点的Y坐标
     *          * 第三个BOX[2] :目标物右下角底部的X坐标
     *          * 第四个BOX[3] :目标物右下角底部的Y坐标
     *          * 第五个BOX[4] :目标物相似度
     *          * 第六个BOX[5] :目标物分类
     *          * 现在扩展到10个，
     *          * 第七个BOX[6] :目标物当前数量，
     *          * 第八个BOX[7] :目标物追踪确认状态，
     *          * 第九个BOX[8] :目标物中心点X坐标
     *          * 第十个BOX[9] :目标物中心点Y坐标
     * @param img 用于后期的特征值模型提取用，
     * @param confThreshold 目标最低相似度，
     * @param iouMathThreshold iou匹配的最小值
     * @param trackerClsList 目标跟踪类别，在这里面就跟踪
     * @param
     * @return <></>
     */
    public float[][] detectorTrackers(float[][] detectorData , Mat img, float confThreshold, float iouMathThreshold
            , List<Integer> trackerClsList, String sortFeatureFlag, Letterbox letterbox)
    {
        clsBoxHashMap.clear();
        detList.clear();



        /* float[][] detectorData
         * 原有的识别物的BOX 向量是6个，
         * 第一个BOX[0] :目标物左上角顶点的X坐标
         * 第二个BOX[1] :目标物左上角顶点的Y坐标
         * 第三个BOX[2] :目标物右下角底部的X坐标
         * 第四个BOX[3] :目标物右下角底部的Y坐标
         * 第五个BOX[4] :目标物相似度
         * 第六个BOX[5] :目标物分类
         * 现在扩展到10个，
         * 第七个BOX[6] :目标物当前数量，
         * 第八个BOX[7] :目标物追踪确认状态，
         * 第九个BOX[8] :目标物中心点X坐标
         * 第十个BOX[9] :目标物中心点Y坐标
         * */
        int i=0;
        //仅取超过可信度的数据
        float[] updatedBox = new float[8];
        int c=0;
        for (float[] box : detectorData) {

            if (box[4] < confThreshold) {
                continue;
            }
            c=c+1;
        }
        float[][] detectorUpdatedData=new float[c][10];
        for (float[] box : detectorData) {

            if (box[4] < confThreshold) {
                continue;
            }
            updatedBox = Arrays.copyOf(box, 10);
            detectorUpdatedData[i] = updatedBox;
            detectorUpdatedData[i][8]=(box[0] + box[2]) / 2;
            detectorUpdatedData[i][9]=(box[1] + box[3]) / 2;
            i=i+1;

        }

        for (int cN:trackerClsList
        ) {
            ArrayList<float[]> detectorClsData =new ArrayList();
            for (float[] box : detectorUpdatedData ) {
                if((int)box[5]==cN){

                    detectorClsData.add(box);
                }
            }
            clsBoxHashMap.put(cN,detectorClsData);
        }

        clsBoxHashMap.forEach((clsTypeNum, detectorList) -> {

            if (clsTrackerHashMap.containsKey(clsTypeNum)){
                tracker=clsTrackerHashMap.get(clsTypeNum);
            }else{
                tracker=  new ObjectTracker();
                clsTrackerHashMap.put(clsTypeNum,tracker);
            }
            ArrayList clsCenterData =new ArrayList();
            int z=detectorList.size();
            for (int m=0;m<z;m++){
                clsCenterData.add(new double[]{
                        ((float[])detectorList.get(m))[8],((float[])detectorList.get(m))[9]
                        ,((float[])detectorList.get(m))[0],((float[])detectorList.get(m))[1]
                        ,((float[])detectorList.get(m))[2],((float[])detectorList.get(m))[3]
                });
            }

            if(sortFeatureFlag==null || sortFeatureFlag.equals("")){
                tracker.processDetections(clsCenterData,img,iouMathThreshold,"N",letterbox);
            }else{
                tracker.processDetections(clsCenterData,img,iouMathThreshold,sortFeatureFlag,letterbox);
            }

            List<ObjectTracker.TrackInfo> tracksClList=tracker.getDetTracks();
            for(int w=0;w<tracksClList.size();w++){
                ((float[])detectorList.get(w))[6]=tracksClList.get(w).id;
            }

        });

        float[][] detBoxData=new float[detectorUpdatedData.length][10];

        clsBoxHashMap.forEach((clsTypeNum, detectorList) -> {
            logger.info("clsTypeNum size:"+detectorList.size());
            detList.addAll(detectorList);

        });
        int k=0;
        for (float[] box:detList
        ) {
            detBoxData[k]=box;
            k=k+1;
        }
        //数据返回前，内存释放
        clsBoxHashMap.clear();
        detList.clear();
        updatedBox=null;
        detectorData=null;
        detectorUpdatedData=null;
        return  detBoxData;





    }
    public  void release(){
        tracker.release();
        clsBoxHashMap.clear();
        clsTrackerHashMap.clear();
        detList.clear();

    }

    private static void printTracks(List<ObjectTracker.TrackInfo> tracks) {
        System.out.println("");
        System.out.println("Active Tracks:");
        for (ObjectTracker.TrackInfo t : tracks) {

            System.out.printf("ID:%d @(%.1f,%.1f) Age:%d%n",
                    t.id, t.x, t.y, t.age);
        }
    }
}